package data;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;

import play.libs.Json;

import jiyici.Client2ServerSyncData;
import jiyici.Client2ServerSyncItem;
import jiyici.Server2ClientSyncData;
import jiyici.Server2ClientSyncItem;
import jiyici.Constant.ModelColumn;
import models.Category;
import models.Item;
import models.ItemParam;
import models.Record;
import models.RecordParam;
import models.ServerBaseModel;
import models.User;

public class ServerSyncManager {
    
    private static final String[] SYNC_TABLES = { Category.class.getSimpleName(), Item.class.getSimpleName(),
        ItemParam.class.getSimpleName(), Record.class.getSimpleName(), RecordParam.class.getSimpleName() };
    
    public static JsonNode syncServer2Client(final User user, final Server2ClientSyncData syncData) {
        ObjectNode data = Json.newObject();
        ArrayNode updatesArrayNode = data.arrayNode();
        ArrayList<Server2ClientSyncItem> items = syncData.getItems();
        int size = items.size();
        for (int i = 0; i < size; i++) {
            Server2ClientSyncItem item = items.get(i);
            String tableName = item.getTableName();
            ObjectNode tableNode = Json.newObject();
            tableNode.put("tableName", tableName);
            ArrayNode rowsArrayNode = tableNode.arrayNode();
            int updateSize = 0;
            if (Category.class.getSimpleName().equals(tableName)) {
                List<Category> updates = Category.modifiedAfter(user, item.getLastmodified());
                updateSize = updates.size();
                for (int j = 0; j < updateSize; j++) {
                    rowsArrayNode.add(updates.get(j).toJson());
                }
            } else if (Item.class.getSimpleName().equals(tableName)) {
                List<Item> updates = Item.modifiedAfter(user, item.getLastmodified());
                updateSize = updates.size();
                for (int j = 0; j < updateSize; j++) {
                    rowsArrayNode.add(updates.get(j).toJson());
                }
            } else if (ItemParam.class.getSimpleName().equals(tableName)) {
                List<ItemParam> updates = ItemParam.modifiedAfter(user, item.getLastmodified());
                updateSize = updates.size();
                for (int j = 0; j < updateSize; j++) {
                    rowsArrayNode.add(updates.get(j).toJson());
                }
            } else if (Record.class.getSimpleName().equals(tableName)) {
                List<Record> updates = Record.modifiedAfter(user, item.getLastmodified());
                updateSize = updates.size();
                for (int j = 0; j < updateSize; j++) {
                    rowsArrayNode.add(updates.get(j).toJson());
                }
            } else if (RecordParam.class.getSimpleName().equals(tableName)) {
                List<RecordParam> updates = RecordParam.modifiedAfter(user, item.getLastmodified());
                updateSize = updates.size();
                for (int j = 0; j < updateSize; j++) {
                    rowsArrayNode.add(updates.get(j).toJson());
                }
            }
            tableNode.put("rows", rowsArrayNode);
            if (updateSize > 0)/* don't transfer empty data, save bandwidth */
                updatesArrayNode.add(tableNode);
        }
        data.put("updates", updatesArrayNode);
        return data;
    }
    
    public static JsonNode syncClient2Server(Client2ServerSyncData syncData) {
        ObjectNode data = Json.newObject();
        ArrayNode dirtyArrayNode = data.arrayNode();
        ArrayList<Client2ServerSyncItem> items = syncData.getItems();
        int size = items.size();
        for (int i = 0; i < size; i++) {
            Client2ServerSyncItem item = items.get(i);
            ObjectNode dirtyNode = Json.newObject();
            dirtyNode.put("tableName", item.tableName);
            ArrayNode rowArray = dirtyNode.arrayNode();
            int modelSize = item.getModels().size();
            for (int j = 0; j < modelSize; j++) {
                ServerBaseModel model = item.getModels().get(j);
                long previousLastmodified = model.lastmodified;
                model.lastmodified = ServerTime.getCurrentTime();
                if (previousLastmodified == 0L)
                    model.save();
                else
                    model.update();
                ObjectNode rowNode = Json.newObject();
                rowNode.put(ModelColumn.BASE_COLUMN_ID, model.getId());
                rowNode.put(ModelColumn.BASE_COLUMN_LASTMODIFIED, model.lastmodified);
                rowArray.add(rowNode);
            }
            dirtyNode.put("rows", rowArray);
            dirtyArrayNode.add(dirtyNode);
        }
        data.put("dirty", dirtyArrayNode);
        return data;
    }

}
